/**
 * 懒加载工具类
 * 提供图片懒加载、组件懒加载、数据懒加载等功能
 */

/**
 * 图片懒加载类
 */
export class ImageLazyLoader {
  constructor(options = {}) {
    this.root = options.root || null;
    this.threshold = options.threshold || 0.1;
    this.rootMargin = options.rootMargin || '0px';
    this.observer = null;
    this.images = new Set();
    this.loadedImages = new Set();
    this.failedImages = new Set();
    this.placeholder = options.placeholder || '';
    this.errorImage = options.errorImage || '';
    this.init();
  }

  init() {
    if ('IntersectionObserver' in window) {
      this.observer = new IntersectionObserver(
        this.handleIntersection.bind(this),
        {
          root: this.root,
          threshold: this.threshold,
          rootMargin: this.rootMargin
        }
      );
    } else {
      console.warn('IntersectionObserver not supported, falling back to immediate loading');
    }
  }

  /**
   * 观察图片元素
   * @param {HTMLElement} element 图片元素
   * @param {string} src 图片源地址
   * @param {Object} options 选项
   */
  observe(element, src, options = {}) {
    if (!element || !src) return;

    // 设置占位符
    element.src = this.placeholder;
    element.dataset.src = src;
    element.dataset.loading = 'true';
    
    // 添加样式类
    element.classList.add('lazy-image');
    if (options.className) {
      element.classList.add(options.className);
    }

    // 如果已经加载过，直接显示
    if (this.loadedImages.has(src)) {
      this.loadImage(element, src);
      return;
    }

    // 如果加载失败过，显示错误图片
    if (this.failedImages.has(src)) {
      this.showError(element);
      return;
    }

    // 添加到观察列表
    this.images.add(element);
    
    if (this.observer) {
      this.observer.observe(element);
    } else {
      // 降级处理：立即加载
      this.loadImage(element, src);
    }
  }

  /**
   * 停止观察图片元素
   * @param {HTMLElement} element 图片元素
   */
  unobserve(element) {
    if (this.observer && element) {
      this.observer.unobserve(element);
    }
    this.images.delete(element);
  }

  /**
   * 处理交叉观察
   * @param {IntersectionObserverEntry[]} entries 观察条目
   */
  handleIntersection(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const element = entry.target;
        const src = element.dataset.src;
        
        if (src) {
          this.loadImage(element, src);
          this.unobserve(element);
        }
      }
    });
  }

  /**
   * 加载图片
   * @param {HTMLElement} element 图片元素
   * @param {string} src 图片源地址
   */
  loadImage(element, src) {
    if (!element || !src) return;

    const img = new Image();
    
    img.onload = () => {
      element.src = src;
      element.classList.remove('lazy-image');
      element.classList.add('loaded');
      element.dataset.loading = 'false';
      this.loadedImages.add(src);
      
      // 触发加载完成事件
      element.dispatchEvent(new CustomEvent('lazy:loaded', {
        detail: { src, element }
      }));
    };

    img.onerror = () => {
      this.showError(element);
      this.failedImages.add(src);
      
      // 触发加载失败事件
      element.dispatchEvent(new CustomEvent('lazy:error', {
        detail: { src, element }
      }));
    };

    img.src = src;
  }

  /**
   * 显示错误图片
   * @param {HTMLElement} element 图片元素
   */
  showError(element) {
    element.src = this.errorImage;
    element.classList.remove('lazy-image');
    element.classList.add('error');
    element.dataset.loading = 'false';
  }

  /**
   * 预加载图片
   * @param {string[]} urls 图片URL数组
   * @returns {Promise} 预加载Promise
   */
  preloadImages(urls) {
    const promises = urls.map(url => {
      return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(url);
        img.onerror = () => reject(url);
        img.src = url;
      });
    });

    return Promise.allSettled(promises);
  }

  /**
   * 销毁观察器
   */
  destroy() {
    if (this.observer) {
      this.observer.disconnect();
    }
    this.images.clear();
    this.loadedImages.clear();
    this.failedImages.clear();
  }
}

/**
 * 组件懒加载类
 */
export class ComponentLazyLoader {
  constructor(options = {}) {
    this.root = options.root || null;
    this.threshold = options.threshold || 0.1;
    this.observer = null;
    this.components = new Map();
    this.loadedComponents = new Set();
    this.init();
  }

  init() {
    if ('IntersectionObserver' in window) {
      this.observer = new IntersectionObserver(
        this.handleIntersection.bind(this),
        {
          root: this.root,
          threshold: this.threshold
        }
      );
    }
  }

  /**
   * 注册懒加载组件
   * @param {string} name 组件名称
   * @param {Function} loader 组件加载函数
   * @param {Object} options 选项
   */
  register(name, loader, options = {}) {
    this.components.set(name, {
      loader,
      loaded: false,
      component: null,
      options
    });
  }

  /**
   * 观察组件元素
   * @param {HTMLElement} element 组件元素
   * @param {string} componentName 组件名称
   */
  observe(element, componentName) {
    if (!element || !this.components.has(componentName)) return;

    element.dataset.component = componentName;
    element.dataset.loading = 'true';
    element.classList.add('lazy-component');

    if (this.observer) {
      this.observer.observe(element);
    } else {
      // 降级处理：立即加载
      this.loadComponent(element, componentName);
    }
  }

  /**
   * 停止观察组件元素
   * @param {HTMLElement} element 组件元素
   */
  unobserve(element) {
    if (this.observer && element) {
      this.observer.unobserve(element);
    }
  }

  /**
   * 处理交叉观察
   * @param {IntersectionObserverEntry[]} entries 观察条目
   */
  handleIntersection(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const element = entry.target;
        const componentName = element.dataset.component;
        
        if (componentName) {
          this.loadComponent(element, componentName);
          this.unobserve(element);
        }
      }
    });
  }

  /**
   * 加载组件
   * @param {HTMLElement} element 组件元素
   * @param {string} componentName 组件名称
   */
  async loadComponent(element, componentName) {
    const componentConfig = this.components.get(componentName);
    if (!componentConfig) return;

    try {
      if (!componentConfig.loaded) {
        componentConfig.component = await componentConfig.loader();
        componentConfig.loaded = true;
      }

      // 渲染组件
      this.renderComponent(element, componentConfig.component, componentConfig.options);
      
      element.classList.remove('lazy-component');
      element.classList.add('loaded');
      element.dataset.loading = 'false';

      // 触发加载完成事件
      element.dispatchEvent(new CustomEvent('lazy:component:loaded', {
        detail: { componentName, element }
      }));

    } catch (error) {
      console.error(`Failed to load component ${componentName}:`, error);
      element.classList.add('error');
      
      // 触发加载失败事件
      element.dispatchEvent(new CustomEvent('lazy:component:error', {
        detail: { componentName, element, error }
      }));
    }
  }

  /**
   * 渲染组件
   * @param {HTMLElement} element 组件元素
   * @param {*} component 组件
   * @param {Object} options 选项
   */
  renderComponent(element, component, options = {}) {
    // 这里需要根据具体的组件系统来实现
    // 例如 Vue、React 等
    if (options.render) {
      options.render(element, component);
    }
  }

  /**
   * 销毁观察器
   */
  destroy() {
    if (this.observer) {
      this.observer.disconnect();
    }
    this.components.clear();
    this.loadedComponents.clear();
  }
}

/**
 * 数据懒加载类
 */
export class DataLazyLoader {
  constructor(options = {}) {
    this.root = options.root || null;
    this.threshold = options.threshold || 0.1;
    this.observer = null;
    this.dataLoaders = new Map();
    this.loadedData = new Set();
    this.init();
  }

  init() {
    if ('IntersectionObserver' in window) {
      this.observer = new IntersectionObserver(
        this.handleIntersection.bind(this),
        {
          root: this.root,
          threshold: this.threshold
        }
      );
    }
  }

  /**
   * 注册数据加载器
   * @param {string} name 数据名称
   * @param {Function} loader 数据加载函数
   * @param {Object} options 选项
   */
  register(name, loader, options = {}) {
    this.dataLoaders.set(name, {
      loader,
      loaded: false,
      data: null,
      options
    });
  }

  /**
   * 观察数据元素
   * @param {HTMLElement} element 数据元素
   * @param {string} dataName 数据名称
   */
  observe(element, dataName) {
    if (!element || !this.dataLoaders.has(dataName)) return;

    element.dataset.dataName = dataName;
    element.dataset.loading = 'true';
    element.classList.add('lazy-data');

    if (this.observer) {
      this.observer.observe(element);
    } else {
      // 降级处理：立即加载
      this.loadData(element, dataName);
    }
  }

  /**
   * 停止观察数据元素
   * @param {HTMLElement} element 数据元素
   */
  unobserve(element) {
    if (this.observer && element) {
      this.observer.unobserve(element);
    }
  }

  /**
   * 处理交叉观察
   * @param {IntersectionObserverEntry[]} entries 观察条目
   */
  handleIntersection(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const element = entry.target;
        const dataName = element.dataset.dataName;
        
        if (dataName) {
          this.loadData(element, dataName);
          this.unobserve(element);
        }
      }
    });
  }

  /**
   * 加载数据
   * @param {HTMLElement} element 数据元素
   * @param {string} dataName 数据名称
   */
  async loadData(element, dataName) {
    const dataConfig = this.dataLoaders.get(dataName);
    if (!dataConfig) return;

    try {
      if (!dataConfig.loaded) {
        dataConfig.data = await dataConfig.loader();
        dataConfig.loaded = true;
      }

      // 渲染数据
      this.renderData(element, dataConfig.data, dataConfig.options);
      
      element.classList.remove('lazy-data');
      element.classList.add('loaded');
      element.dataset.loading = 'false';

      // 触发加载完成事件
      element.dispatchEvent(new CustomEvent('lazy:data:loaded', {
        detail: { dataName, element, data: dataConfig.data }
      }));

    } catch (error) {
      console.error(`Failed to load data ${dataName}:`, error);
      element.classList.add('error');
      
      // 触发加载失败事件
      element.dispatchEvent(new CustomEvent('lazy:data:error', {
        detail: { dataName, element, error }
      }));
    }
  }

  /**
   * 渲染数据
   * @param {HTMLElement} element 数据元素
   * @param {*} data 数据
   * @param {Object} options 选项
   */
  renderData(element, data, options = {}) {
    if (options.render) {
      options.render(element, data);
    }
  }

  /**
   * 销毁观察器
   */
  destroy() {
    if (this.observer) {
      this.observer.disconnect();
    }
    this.dataLoaders.clear();
    this.loadedData.clear();
  }
}

/**
 * 通用懒加载管理器
 */
export class LazyLoadManager {
  constructor(options = {}) {
    this.imageLoader = new ImageLazyLoader(options.image);
    this.componentLoader = new ComponentLazyLoader(options.component);
    this.dataLoader = new DataLazyLoader(options.data);
  }

  /**
   * 观察图片
   * @param {HTMLElement} element 图片元素
   * @param {string} src 图片源地址
   * @param {Object} options 选项
   */
  observeImage(element, src, options = {}) {
    this.imageLoader.observe(element, src, options);
  }

  /**
   * 观察组件
   * @param {HTMLElement} element 组件元素
   * @param {string} componentName 组件名称
   */
  observeComponent(element, componentName) {
    this.componentLoader.observe(element, componentName);
  }

  /**
   * 观察数据
   * @param {HTMLElement} element 数据元素
   * @param {string} dataName 数据名称
   */
  observeData(element, dataName) {
    this.dataLoader.observe(element, dataName);
  }

  /**
   * 预加载图片
   * @param {string[]} urls 图片URL数组
   * @returns {Promise} 预加载Promise
   */
  preloadImages(urls) {
    return this.imageLoader.preloadImages(urls);
  }

  /**
   * 注册组件
   * @param {string} name 组件名称
   * @param {Function} loader 组件加载函数
   * @param {Object} options 选项
   */
  registerComponent(name, loader, options = {}) {
    this.componentLoader.register(name, loader, options);
  }

  /**
   * 注册数据加载器
   * @param {string} name 数据名称
   * @param {Function} loader 数据加载函数
   * @param {Object} options 选项
   */
  registerData(name, loader, options = {}) {
    this.dataLoader.register(name, loader, options);
  }

  /**
   * 销毁所有观察器
   */
  destroy() {
    this.imageLoader.destroy();
    this.componentLoader.destroy();
    this.dataLoader.destroy();
  }
}

/**
 * 创建懒加载管理器
 * @param {Object} options 选项
 * @returns {LazyLoadManager} 懒加载管理器
 */
export function createLazyLoadManager(options = {}) {
  return new LazyLoadManager(options);
}

/**
 * 创建图片懒加载器
 * @param {Object} options 选项
 * @returns {ImageLazyLoader} 图片懒加载器
 */
export function createImageLazyLoader(options = {}) {
  return new ImageLazyLoader(options);
}

/**
 * 创建组件懒加载器
 * @param {Object} options 选项
 * @returns {ComponentLazyLoader} 组件懒加载器
 */
export function createComponentLazyLoader(options = {}) {
  return new ComponentLazyLoader(options);
}

/**
 * 创建数据懒加载器
 * @param {Object} options 选项
 * @returns {DataLazyLoader} 数据懒加载器
 */
export function createDataLazyLoader(options = {}) {
  return new DataLazyLoader(options);
}

export default {
  ImageLazyLoader,
  ComponentLazyLoader,
  DataLazyLoader,
  LazyLoadManager,
  createLazyLoadManager,
  createImageLazyLoader,
  createComponentLazyLoader,
  createDataLazyLoader
};
